package com.jin.webvideo.base.spring.interceptor;

import com.jin.webvideo.base.LoginHandler;
import com.jin.webvideo.base.util.CollectionsUtil;
import com.jin.webvideo.base.util.ObjectsUtil;
import com.jin.webvideo.service.ConfigService;
import com.jin.webvideo.util.base.DateUtil;
import com.jin.webvideo.util.consts.ConfigConst;
import com.jin.webvideo.util.consts.CookieConst;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

public class LoginInterceptor implements HandlerInterceptor, InterceptorChainItem {
    private ConfigService configService;

    // 不设置自动登录的页面
    private String[] excludePathAutoLogin = ObjectsUtil.Empty.STRINGS;
    private PathMatcher matcher = new AntPathMatcher();
    private LoginHandler processor;

    private CollectionsUtil.MapConverter cookieConverter = new CollectionsUtil.MapConverter<Cookie, String, String>() {
        @Override
        public String convertKey(Cookie accept) {
            return accept.getName();
        }

        @Override
        public String convertVal(Cookie accept) {
            return accept.getValue();
        }
    };

    public void excludePathAutoLogin(String... patterns){
        this.excludePathAutoLogin = patterns;
    }

    public LoginInterceptor(ConfigService configService, LoginHandler processor){
        this.configService = configService;
        this.processor = processor;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 只处理非ajax请求
        if (!isAjax(request)) {
            // processor处理成功，处理登陆页面 登录请求 登出请求
            if (processor.loginHandle(request, response)) {
                return false;
            }
            // 如果get请求，非ajax 匹配自动登录页面，则自动登录
            if (request.getMethod().equalsIgnoreCase("GET") && matchAutoLogin(request.getRequestURI())){
                // 进行自动登录处理
                autoLogin(request, response);
            }
        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HttpSession session = request.getSession();
        // 设置是否登录标志
        if (LoginHandler.loggedIn(session)) {
            request.setAttribute("isLogin", true);
            // 设置用户信息
            request.setAttribute("user", LoginHandler.getSessionStore(session).getUser());
        }
        else {
            request.setAttribute("isLogin", false);
        }
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    /**
     * 自动登录
     * @param request
     * @param response
     */
    private void autoLogin(HttpServletRequest request, HttpServletResponse response){
        HttpSession session = request.getSession();
        // 未登录
        if (!LoginHandler.loggedIn(session)){
            Cookie[] cookies = ObjectsUtil.getOrDefault(request.getCookies(), new Cookie[0]);
            // 拿Cookie
            Map<String,String> cookieMap = CollectionsUtil.convert(Arrays.asList(cookies), cookieConverter);
            // 设置了自动登录
            if (true == Boolean.valueOf(cookieMap.get(CookieConst.AUTO_LOGIN))){
                Map<String,String> config = configService.configMapByGroupId(ConfigConst.PASSWORD_CONFIG);
                // 配置生效时间
                Date effectiveTime = DateUtil.format(config.getOrDefault(ConfigConst.ATTR_CONFIG_EFFECTIVETIME, DateUtil.DATE_DEFAULT), DateUtil.FORMAT_DEFAULT);
                // 上次登录时间
                Date loginTime = DateUtil.format(cookieMap.getOrDefault(CookieConst.LOGIN_TIME, DateUtil.DATE_DEFAULT), DateUtil.FORMAT_DEFAULT);
                // 配置生效时间 > 上次登录时间，即存储的信息是由之前的配置计算获得的，本次无法解密，不进行处理
                if (effectiveTime == null || loginTime == null || loginTime.before(effectiveTime) ) {
                    return;
                }
                // 获取基本信息
                String account = cookieMap.get(CookieConst.ACCOUNT);
                String password = cookieMap.get(CookieConst.PASSWORD);
                // 调用登录
                processor.login(request, response, account, password);
            };
        }
    }

    private boolean matchAutoLogin(String path){
        return !match(excludePathAutoLogin, path);
    }

    private boolean match(String[] patterns, String path){
        if (patterns == null || path == null){
            return false;
        }
        for (String pattern : patterns){
            if (matcher.match(pattern, path)){
                return true;
            }
        }
        return false;
    }

    private boolean isAjax(HttpServletRequest request){
        return request.getHeader("x-requested-with") != null
                && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest");
    }
}
